package com.yfqy.app.modules.order.director;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.yfqy.app.constant.OrderConstants;
import com.yfqy.app.domain.entity.ProductSpu;
import com.yfqy.app.domain.entity.PromotionProduct;
import com.yfqy.app.domain.entity.PromotionRule;
import com.yfqy.app.domain.mapper.PromotionRuleMapper;
import com.yfqy.app.enums.ErrorCode;
import com.yfqy.app.enums.OrderType;
import com.yfqy.app.exception.BusinessException;
import com.yfqy.app.modules.order.context.OrderBuilderContext;
import com.yfqy.app.modules.order.dto.OrderAmountDTO;
import com.yfqy.app.modules.order.dto.OrderCreateRequest;
import com.yfqy.app.modules.order.dto.OrderItemRequest;
import com.yfqy.app.modules.promotion.dto.PromotionRuleDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * 满减促销订单
 */
@Service
@Slf4j
public class FullDiscountOrderCreateBuilderDirector extends AbstractOrderCreateBuilderDirector {

    @Autowired
    private PromotionRuleMapper promotionRuleMapper;


    @Override
    public OrderType getOrderType() {
        return OrderType.FULL_DISCOUNT;
    }

    @Override
    public void validRequiredParam(OrderCreateRequest request) {
        validateParams(request);
        specificValidate(request);
    }


    @Override
    public OrderAmountDTO calculateAmount(OrderCreateRequest request) {
        // 1. 重新计算商品总金额
        BigDecimal calculatedTotal = calculateItemTotalAmount(request.getItems().get(0));

        OrderAmountDTO amountDTO = request.getOrderAmountDTO();
        // 2. 校验并修正总金额
        if (amountDTO.getTotalAmount() == null || amountDTO.getTotalAmount().compareTo(calculatedTotal) != 0) {
            log.warn("前端总金额计算错误，已修正。前端值: {}, 计算值: {}", amountDTO.getTotalAmount(), calculatedTotal);
            amountDTO.setTotalAmount(calculatedTotal);
        }

        // 3. 重新计算实付金额（总金额 - 优惠 - 积分抵扣）
        BigDecimal paymentAmount = calculatedTotal;

        // 4. 如果有满减优惠
        PromotionRule rule = getFullDiscountRule();
        if (rule != null) {
            // 达到满减条件
            paymentAmount = paymentAmount.subtract(rule.getReduceAmount()).max(BigDecimal.ZERO);
            amountDTO.setDiscountAmount(rule.getReduceAmount());
        } else {
            amountDTO.setDiscountAmount(BigDecimal.ZERO);
        }

        // 5. 如果有积分抵扣
        if (request.isUsePoints()) {
            applyPointsDeduction(amountDTO, paymentAmount);
        } else {
            resetPointsDeduction(amountDTO);
        }

        // 6. 设置最终实付金额
        paymentAmount = paymentAmount.subtract(amountDTO.getPointAmount()).max(BigDecimal.ZERO);
        amountDTO.setPaymentAmount(paymentAmount);

        // 7. 最终商品实付金额是否免运费
        calculateFreightAmount(amountDTO);

        // 8. 更新前端的amount对象
        request.setOrderAmountDTO(amountDTO);
        return amountDTO;
    }

    @Override
    public void validateProducts(OrderCreateRequest request) {
        // nothing to do
    }

    @Override
    public void specificValidate(OrderCreateRequest request) {

        // 1. 批量获取商品信息并验证
        OrderItemRequest item = request.getItems().get(0);
        Map<Long, ProductSpu> spuMap = validateProductInfo(item);

        // 2. 验证促销活动
        PromotionProduct promotionProduct = getAndValidatePromotion(request.getPromotionId(), item.getSkuId());
        item.setPromotionProductId(promotionProduct.getId());

        // 3. 价格校验
        validatePrice(item, spuMap, promotionProduct);

        // 4. 库存校验
        validateStock(item, spuMap, promotionProduct);

        // 5. 限购校验
        validatePurchaseLimit(item, request.getUserId(), promotionProduct);

        // 6. 满减规则匹配（仅对满减订单）
        validateFullDiscountRules(item, request.getPromotionId());

        log.info("订单特殊校验完成，订单类型：{}", getOrderType());
    }

    // 满减规则
    private void validateFullDiscountRules(OrderItemRequest item, Long promotionId) {
        List<PromotionRule> promotionRules = promotionRuleMapper.selectFullDiscountRules(promotionId);
        if (CollectionUtils.isEmpty(promotionRules)) {
            throw new BusinessException(ErrorCode.PROMOTION_RULE_NOT_FOUND);
        }
        matchFullDiscountRule(item, promotionRules);
    }

    /**
     * 匹配最优的满减配置，并设置到上下文
     *
     * @param item
     * @param promotionRules
     */
    private void matchFullDiscountRule(OrderItemRequest item, List<PromotionRule> promotionRules) {
        try {
            BigDecimal totalAmount = calculateItemTotalAmount(item);

            // 降序排序后找第一条满足条件的规则
            promotionRules.stream()
                    .sorted(Comparator.comparing(PromotionRule::getFullAmount).reversed())
                    .filter(rule -> rule.getFullAmount().compareTo(totalAmount) <= 0)
                    .findFirst()
                    .ifPresent(rule ->
                            OrderBuilderContext.setValue(OrderConstants.FULL_DISCOUNT_CONF, rule)
                    );
        } catch (Exception e) {
            log.error("解析促销配置失败", e);
            throw new BusinessException(ErrorCode.INVALID_PROMOTION_CONFIG);
        }
    }

}
